﻿using System.Collections.Generic;
using System.Data;
using System.Text;
using System;

namespace Domain.Repository
{
    public interface IQueryTemplate
    {
        /// <summary>
        /// 将查询结果封装为IDictionary集合，其它Key值大写
        /// </summary>
        /// <param name="querySql">Sql statement key or Sql string</param>
        /// <param name="queryParameters">查询参数，可为Null</param>
        /// <returns></returns>
        IList<IDictionary<string, object>> QueryForListMap(string querySql, QueryParameters queryParameters);

        /// <summary>
        /// 将查询结果转换为指定类型的实例，支持简单类型和复杂类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="querySql">Sql statement key or Sql string</param>
        /// <param name="queryParameters">查询参数，可为Null</param>
        /// <returns></returns>
        T QueryForObject<T>(string querySql, QueryParameters queryParameters) where T : class;

        /// <summary>
        /// 将查询结果转换为指定类型实例集合，支持简单类型和复杂类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="querySql">Sql statement key or Sql string</param>
        /// <param name="queryParameters">查询参数，可为Null</param>
        /// <returns></returns>
        IList<T> QueryForList<T>(string querySql, QueryParameters queryParameters) where T : class;

        /// <summary>
        /// 分布查询，查询结果封装到Page对象，求数据总数采用默认实现
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="querySql">Sql statement key or Sql string</param>
        /// <param name="queryParameters">查询参数，可为Null</param>
        /// <param name="countStartFrom">求总数是否从From语句开始，true 替换From之前的语句为Select count(1) 进行求总，false 采用嵌套SQL求总</param>
        /// <param name="pageNumber"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        Page<T> QueryForPage<T>(string querySql, QueryParameters queryParameters, bool countStartFrom, long pageNumber, long pageSize) where T : class;

        /// <summary>
        /// 分布查询，查询结果封装到Page对象,求数据总数采用自定义SQL实现
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="querySql">Sql statement key or Sql string</param>
        /// <param name="countSql">求总SQL key or sql string</param>
        /// <param name="queryParameters">查询参数，可为Null</param>
        /// <param name="pageNumber"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        Page<T> QueryForPage<T>(string querySql, string countSql, QueryParameters queryParameters, long pageNumber, long pageSize) where T : class;

        /// <summary>
        /// 分布查询，查询结果封装到Page IDictionary，求数据总数采用默认实现
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="querySql">Sql statement key or Sql string</param>
        /// <param name="queryParameters">查询参数，可为Null</param>
        /// <param name="countStartFrom">求总数是否从From语句开始，true 替换From之前的语句为Select count(1) 进行求总，false 采用嵌套SQL求总</param>
        /// <param name="pageNumber"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        Page<IDictionary<string, object>> QueryForPageMap(string querySql, QueryParameters queryParameters, bool countStartFrom, long pageNumber, long pageSize);


        /// <summary>
        /// 分布查询，查询结果封装到Page IDictionary,求数据总数采用自定义SQL实现
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="querySql">Sql statement key or Sql string</param>
        /// <param name="countSql">求总SQL key or sql string</param>
        /// <param name="queryParameters">查询参数，可为Null</param>
        /// <param name="pageNumber"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        Page<IDictionary<string, object>> QueryForPageMap(string querySql, string countSql, QueryParameters queryParameters, long pageNumber, long pageSize);

        /// <summary>
        /// 已知实体类型和Id，通过反射获取完整实体信息
        /// </summary>
        /// <param name="ownerType"></param>
        /// <param name="ownerId"></param>
        /// <returns></returns>
        object GetEntity(string ownerType, object ownerId);
    }
        
    /// <summary>
    /// 查询参数构建对象
    /// </summary>
    public class QueryParameters
    {
        public static readonly string STR_StartNumber = "startNumber";
        public static readonly string STR_FinishNumber = "finishNumber";

        private IList<QueryParameter> parameters;

        public IList<QueryParameter> Parameters
        {
            get { return parameters; }
        }

        private QueryParameters()
        {
            this.parameters = new List<QueryParameter>();
        }

        public static QueryParameters Create()
        {
            return new QueryParameters();
        }

        public static QueryParameters Create(string name, object value, DbType dbType)
        {
            return Create().Add(name, value, dbType);
        }

        public QueryParameters Add(string name, object value, DbType dbType)
        {
            this.parameters.Add(new QueryParameter(name, value, dbType));
            return this;
        }
    }

    /// <summary>
    /// 查询参数定义
    /// </summary>
    public class QueryParameter
    {
        private string _name;
        private object _value;
        private DbType _dbType;

        public string Name
        {
            get { return _name; }
        }

        public object Value
        {
            get { return _value; }
        }

        public DbType DbType
        {
            get { return _dbType; }
        }

        public QueryParameter(string name, object value, DbType dbType)
        {
            this._name = name;
            this._value = value;
            this._dbType = dbType;
        }

        public override string ToString()
        {
            return new StringBuilder().Append("Name : " + Name).Append("\tValue : " + Value).Append("\tDbType : " + DbType).ToString();
        }
    }
}
